home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Music / EDIT / PerfectSound / source / sed.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-23  |  32.7 KB  |  1,241 lines

  1. /********************************/
  2. /**   Perfect Sound (C) 1986   **/
  3. /**    Anthony J. Wood         **/
  4. /**                            **/
  5. /** FILE 2 of 4                **/
  6. /**                            **/
  7. /** This Source code may be    **/
  8. /** copied for backup only.    **/
  9. /** This Source code is for    **/
  10. /** reference only, you may    **/
  11. /** NOT modify and compile     **/
  12. /** this source except for     **/
  13. /** PERSONAL use. Permission   **/
  14. /** is given to distribute     **/
  15. /** copies of the object code  **/
  16. /** generated from compiling   **/
  17. /** Perfect Sound ONLY if the  **/
  18. /** source code is not changed **/
  19. /** in any way. Permision is   **/
  20. /** granted to use subroutines **/
  21. /** in this file within your   **/
  22. /** own programs if you notify **/
  23. /** SunRize Industries of your **/
  24. /** intent to do so and        **/
  25. /** SunRize Industries agrees  **/
  26. /** to your request.           **/
  27. /**                            **/
  28. /**  SunRize Industries        **/
  29. /**  PO Box 1453               **/
  30. /**  College Station, TX 77841 **/
  31. /**  (409) 846-1311            **/
  32. /**                            **/
  33. /********************************/
  34.  
  35. #include <exec/types.h>
  36. #include <intuition/intuition.h>
  37. #include <stdio.h>
  38. #include <exec/exec.h>
  39. #include <devices/audio.h>
  40. #include <fcntl.h>
  41. #include "graphics/text.h"
  42. #include "df0:sed1.h"
  43.  
  44. #define BUFSIZE 2*1024        /* playback buffers */
  45.  
  46. struct GfxBase *GfxBase;
  47. struct IntuitionBase *IntuitionBase;
  48. char *bufL[2],*bufR[2];
  49. WORD diskchange=TRUE;
  50.  
  51. main()
  52. {
  53.  
  54. extern struct Menu Titles[];
  55. UBYTE cmap[16*3];
  56. int len,memory,samplen,record_delay;
  57. int i,ss,sl,temp;
  58. register int k,j;
  59. int lastp=0;
  60. int cur=0;
  61. ULONG position=0;
  62. struct Samp samp;
  63. char *AllocMem(),*p1,*p2,*x;
  64. static char line[80],buf[80];
  65. static char path[80]="";
  66. UBYTE *pa=0xBFE001;   /* left mouse button is at this address */
  67. SHORT mousex,mousey;
  68. USHORT ops,ope,opp;
  69. ULONG class;
  70. USHORT code,menunum,itemnum,subnum;
  71. SHORT oct[MAX_SAMPLES];
  72. SHORT autograph;
  73. struct TextAttr f;
  74. struct TextFont *font;
  75. struct Gadget *gad;
  76. struct Window *Window;
  77. struct IntuiMessage *message;
  78. struct Gadget *gadget_s,*gadget_e,*gadget_p;
  79. struct PropInfo *prop_s,*prop_e,*prop_p;
  80. struct IOAudio IOB;
  81. struct Image image;
  82. struct Screen *screen=0;
  83. static struct NewWindow NewWindow = {
  84.    0,
  85.    0,
  86.    640,
  87.    200,
  88.    0,
  89.    1,
  90.    MOUSEMOVE|MENUPICK|MOUSEBUTTONS|CLOSEWINDOW|GADGETUP|RAWKEY|DISKINSERTED,
  91.    ACTIVATE|WINDOWCLOSE|WINDOWDEPTH|NOCAREREFRESH,
  92.    0,0,
  93.    "Perfect Sound   Copyright 1986 SunRize Industries  Ver 2.0 ",
  94.    0,0,
  95.    0,0,0,0,
  96.    WBENCHSCREEN
  97.    };
  98.  
  99. static USHORT arrowsData[] =
  100. {
  101.  
  102. 0x0000,0x0000,0x0018,0x6000,0x0078,0x7800,
  103. 0x01F8,0x7E00,0x07F8,0x7F80,0x1FF8,0x7FE0,
  104. 0x07F8,0x7F80,0x01F8,0x7E00,0x0078,0x7800,
  105. 0x0018,0x6000,0x0000,0x0000,0x776F,0x726B,
  106. 0x696E,0x672E,0x2E2E,0x6E6C,0x792E,0x0A0A,
  107. 0x2062,0x6520,0x6672,0x6565,0x6C79,0x2064,
  108. 0x6973,0x7472,0x6962,0x7574,0x6564,0x2066,
  109. 0x6F72,0x206E,0x6F6E,0x2D70,0x726F,0x6669,
  110. 0x740A,0x0000,0x0000,0x0000,0x0000,0x0000,
  111. 0x0000,0x0000,0x0000,0x7C0C,0xF03B,0x3C0C,
  112. 0x3BF0,0x3C00,0x0000,0x663B,0x633C,0x0018,
  113. };
  114. static struct Image arrows =
  115. {
  116. 0,0,          /* LeftEdge, TopEdge */
  117. 30,10,1,      /* Width, Height, Depth */
  118. 0,             /* put arrowmem here */
  119. 0x1,0,        /* PlanePick, PlaneOnOff */
  120. NULL,        /* Pointer to next Image */
  121. };
  122.  
  123.  
  124. /* Open up the Intuition interface -- a window */
  125.  
  126. IntuitionBase=(struct IntuitionBase *)
  127.    OpenLibrary("intuition.library",INTUITION_REV);
  128. if (IntuitionBase==NULL) {
  129.    printf("Can't open window libraries\n\n");
  130.    exit(10);
  131.    }
  132.  
  133. /* open graphics library */
  134.  
  135. GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0);
  136. if (GfxBase==NULL) {
  137.    printf("Can't open graphics library\n\n");
  138.    exit(0);
  139.    }
  140.  
  141.  
  142. /*** load the title screen if it exists ***/
  143.  
  144. if (load_ilbm("ps.title",&image,cmap)!=-1) {
  145.    screen=openscr(image.Width,image.Depth);
  146.    if (screen==0) {
  147.       printf("Can't open screen!\n");
  148.       exit(10);
  149.       }
  150.  
  151.    for (i=0;i<16*3;i=i+3)
  152.       SetRGB4(&screen->ViewPort,i/3,cmap[i]>>4,cmap[i+1]>>4,cmap[i+2]>>4);
  153.    DrawImage(&screen->RastPort,&image,0,0);
  154.    MoveScreen(screen,0,-199);
  155.    }
  156.  
  157. if ((arrows.ImageData=AllocMem(sizeof(arrowsData),MEMF_CHIP))==0) {
  158.    printf("Can't allocate gadget memory!\n");
  159.    exit(0);
  160.    }
  161. movmem(&arrowsData[0],arrows.ImageData,sizeof(arrowsData));
  162.  
  163. /**** allocate "double buffers" for audio device ****/
  164.  
  165. for (i=0;i<2;i++) {
  166.    if ((bufL[i]=AllocMem(BUFSIZE,MEMF_CHIP))==0) {
  167.       printf("Can't allocate buffer memory!\n");
  168.       exit(0);
  169.       }
  170.  
  171.    if ((bufR[i]=AllocMem(BUFSIZE,MEMF_CHIP))==0) {
  172.       printf("Can't allocate buffer memory!\n");
  173.       exit(0);
  174.       }
  175.    }
  176.  
  177.  
  178. /* inilize sample array to zero */
  179.  
  180. for(i=0;i<MAX_SAMPLES;i++) {
  181.    samp.lmem[i]=0;
  182.    samp.rmem[i]=0;
  183.    samp.length[i]=0;
  184.    samp.rate[i]=0;
  185.    samp.name[i]=0;
  186.    samp.sm[i]=0;
  187.    samp.em[i]=0;
  188.    samp.ctoctave[i]=0;
  189.    samp.oneshot[i]=0;
  190.    samp.repeat[i]=0;
  191.    samp.cycles[i]=0;
  192.    }
  193.  
  194. ops=-1;
  195. ope=-1;
  196. opp=-1;
  197.  
  198.  
  199. /* initilize menu and gadget structures */
  200.  
  201. gadget_s=(struct Gadget *)makegadget();
  202. gadget_e=(struct Gadget *)gadget_s->NextGadget;
  203. gadget_p=(struct Gadget *)gadget_e->NextGadget;
  204. prop_s=(struct PropInfo *)gadget_s->SpecialInfo;
  205. prop_e=(struct PropInfo *)gadget_e->SpecialInfo;
  206. prop_p=(struct PropInfo *)gadget_p->SpecialInfo;
  207.  
  208. NewWindow.FirstGadget=gadget_s;
  209.  
  210.  
  211. if ((Window=(struct Window *)OpenWindow(&NewWindow))==NULL) {
  212.    printf("Can't Open Window\n\n");                   
  213.    exit(10);
  214.    }
  215.  
  216.  
  217. /* Always use TOPAZ_80 */
  218.  
  219. f.ta_Name="topaz.font";
  220. f.ta_YSize=8;
  221. f.ta_Style=0;
  222. f.ta_Flags=0;
  223. font=(struct TextFont *)OpenFont(&f);
  224. if (font==0) {
  225.    printf("Can't Open font!\n\n");
  226.    exit(0);
  227.    }
  228. SetFont(Window->RPort,font);
  229.  
  230. /* paint screen black */
  231.  
  232. SetAPen(Window->RPort,BLACK);
  233. SetBPen(Window->RPort,BLACK);
  234. RectFill(Window->RPort,2,10,637,198);
  235.  
  236. /* add a white line seperating status from samples */
  237. drawline(Window,2,GPP-4,637,GPP-4,WHITE);
  238. drawline(Window,2,GPP-5,637,GPP-5,WHITE);
  239.  
  240.  
  241. /* tell intuition about menus */
  242.  
  243. SetMenuStrip(Window,Titles);
  244.  
  245. /* draw arrows on left of gadget */
  246.  
  247. DrawImage (Window->RPort,&arrows,606,GPP);
  248. DrawImage (Window->RPort,&arrows,606,GSP);
  249. DrawImage (Window->RPort,&arrows,606,GEP);
  250.  
  251. /* allocate audio chanels 1 and 2 */
  252.  
  253. allocate_channel (Window,&IOB);
  254.  
  255. /** load some sample sounds if they are on the disk **/
  256. if (screen!=0) {
  257.    if (load_it(Window,&cur,&samp,"sounds/demo1","bang")!=-1)
  258.    samp.em[cur]=samp.length[cur];
  259.    if (load_it(Window,&cur,&samp,"sounds/demo2","Welcome")!=-1)
  260.       samp.em[cur]=samp.length[cur];
  261.    if (load_it(Window,&cur,&samp,"sounds/demo3","Button")!=-1)
  262.       samp.em[cur]=samp.length[cur];
  263.  
  264. /**** play the loaded sounds ******/
  265.    if (cur==2) {
  266.       prop_e->HorizPot=0xFFFF;ope=0xFFFF;
  267.       prop_p->HorizPot=0;opp=0;
  268.       prop_s->HorizPot=0;ops=0;
  269.       play(Window,&IOB,0,samp.length[0],&samp,0);
  270.       for (k=124;k<=300;k=k+50) {
  271.          samp.rate[1]=k;
  272.          play(Window,&IOB,1,samp.length[1],&samp,1);
  273.          }
  274.       samp.rate[1]=358;
  275.       play(Window,&IOB,1,samp.length[1],&samp,1);
  276.       for (k=0;k<50000;k++) ;
  277.       play(Window,&IOB,2,samp.length[2],&samp,2);
  278.       }
  279.    while ((*pa&64)==64) ;
  280.    CloseScreen(screen);
  281.    FreeMem(image.ImageData,image.Width/8*image.Height*image.Depth);
  282.    }
  283.  
  284. RefreshGadgets(gadget_s,Window,NULL);
  285. msg(Window,"Welcome to Perfect Sound.");
  286.  
  287. memory=frags();    /* find largest amount of free memeory */
  288. record_delay=5;     /* period of 362 is default */
  289. autograph=FALSE;
  290.  
  291.  
  292.  
  293. /* print gadget labels */
  294.  
  295. putxy(Window,4,GSP+2,"START",WHITE,BLACK);
  296. putxy(Window,4,GEP+2,"END",WHITE,BLACK);
  297. putxy(Window,4,GPP+2,"POS'N",WHITE,BLACK);
  298.  
  299.  
  300.  
  301. goto update;     /* print screen at bottom */
  302.  
  303. ignore:
  304.  
  305. SetMenuStrip(Window,Titles);   /* turn on menus */
  306.  
  307. if((message=(struct IntuiMessage *)GetMsg(Window->UserPort))==0) {
  308.    Wait(1<<Window->UserPort->mp_SigBit);
  309.    goto ignore;
  310.    }
  311. class=message->Class;
  312. code=message->Code;
  313. mousex=message->MouseX;
  314. mousey=message->MouseY;
  315. gad=(struct Gadget *)message->IAddress;
  316. ReplyMsg(message);
  317. ClearMenuStrip(Window);
  318.  
  319. if (class==MOUSEMOVE) {       /* moving proportional gadget */
  320.    do {
  321.       if (prop_s->HorizPot!=ops) {
  322.          ops=prop_s->HorizPot;
  323.          samp.sm[cur]=(prop_s->HorizPot>>7)*samp.length[cur];
  324.          samp.sm[cur]/=0x01FF;
  325.          lastp=samp.sm[cur];
  326.          }
  327.       if (prop_e->HorizPot!=ope) {
  328.          ope=prop_e->HorizPot;
  329.          samp.em[cur]=(prop_e->HorizPot>>7)*samp.length[cur];
  330.          samp.em[cur]/=0x01FF;
  331.          lastp=samp.em[cur];
  332.          }
  333.       if (prop_p->HorizPot!=opp) {
  334.          opp=prop_p->HorizPot;
  335.          position=(prop_p->HorizPot>>7)*samp.length[cur];
  336.          position/=0x01FF;
  337.          lastp=position;
  338.          }
  339.       message=(struct IntuiMessage *)GetMsg(Window->UserPort);
  340.       if (message==0)  break;
  341.       class=message->Class;
  342.       code=message->Code;
  343.       mousex=message->MouseX;
  344.       mousey=message->MouseY;
  345.       gad=(struct Gadget *)message->IAddress;
  346.       ReplyMsg(message);
  347.    } while (class==MOUSEMOVE);
  348.    if (autograph==TRUE) goto graphit;
  349.    }
  350.  
  351. if (class==CLOSEWINDOW) {
  352.    CloseFont(font);
  353.    ClearMenuStrip(Window);
  354.    deallocate_channel (&IOB);
  355.    CloseWindow(Window);
  356.    CloseLibrary(IntuitionBase);
  357.    for(i=0;i<MAX_SAMPLES;i++)
  358.       if (samp.lmem[i]!=0) {
  359.          FreeMem(samp.lmem[i],samp.length[i]);
  360.          FreeMem(samp.name[i],strlen(samp.name[i])+1);
  361.          if (samp.type[i]==STEREO)
  362.             FreeMem(samp.rmem[i],samp.length[i]);
  363.          }
  364.  
  365.    FreeMem(arrows.ImageData,sizeof(arrowsData));
  366.    for (i=0;i<2;i++) {
  367.       FreeMem(bufL[i],BUFSIZE);
  368.       FreeMem(bufR[i],BUFSIZE);
  369.       }
  370.  
  371.    exit(0);
  372.    }
  373.  
  374. if (class==MOUSEBUTTONS) {        /* selecting a new cur */
  375.    if (code!=SELECTDOWN) goto ignore;
  376.  
  377.    if (mousey<GEP+11 && mousey>GEP) {
  378.       alter(&samp.em[cur],samp.length[cur],mousex);
  379.       lastp=samp.em[cur];
  380.       if (autograph==TRUE) goto graphit;
  381.       goto update;
  382.       }
  383.  
  384.    if (mousey<GEP && mousey>GSP) {
  385.       alter(&samp.sm[cur],samp.length[cur],mousex);
  386.       lastp=samp.sm[cur];
  387.       if (autograph==TRUE) goto graphit;
  388.       goto update;
  389.       }
  390.       
  391.    if (mousey<GPP+11 && mousey>GPP) {
  392.       alter(&position,samp.length[cur],mousex);
  393.       lastp=position;
  394.       if (autograph==TRUE) goto graphit;
  395.       goto update;
  396.       }
  397.    mousey=(mousey-11)/8;
  398.    if (mousex>320) mousey+=MAX_SAMPLES/2;
  399.    if (mousey<MAX_SAMPLES && samp.lmem[mousey]!=0) {
  400.       if (cur==mousey) {
  401.          play(Window,&IOB,0,samp.length[cur],&samp,cur);
  402.          goto ignore;
  403.          }
  404.       PutName(Window,samp.name[cur],cur,REG_VID);
  405.       cur=mousey;
  406.       PutName(Window,samp.name[cur],cur,REV_VID);
  407.  
  408.       ModifyProp(gadget_s,Window,0,AUTOKNOB|FREEHORIZ,
  409.       samp.sm[cur]*0xFFFF/samp.length[cur],0,0,0xFFFF);
  410.  
  411.       ModifyProp(gadget_e,Window,0,AUTOKNOB|FREEHORIZ,
  412.       samp.em[cur]*0xFFFF/samp.length[cur],0,0,0xFFFF);
  413.  
  414.       ModifyProp(gadget_p,Window,0,AUTOKNOB|FREEHORIZ,0,0,0,0xFFFF);
  415.  
  416.       lastp=0;
  417.       position=0;
  418.       if (samp.ctoctave[cur]>1 || samp.repeat[cur]!=0) {
  419.       sprintf(line,"OneShotHiSamples %d  RepeatHiSamples %d No. Octaves %d",
  420.          samp.oneshot[cur],samp.repeat[cur],samp.ctoctave[cur]);
  421.       msg(Window,line);
  422.       }
  423.       }
  424.       if (autograph==TRUE) goto graphit;
  425.       goto update;
  426.    }
  427. if (class==DISKINSERTED) {
  428.    diskchange=TRUE;
  429.    goto ignore;
  430.    }
  431.  
  432. if (class==RAWKEY) {
  433.    if (code>89 || code<80)  goto ignore;
  434.    if (samp.ctoctave[cur]==0) {
  435.       msg(Window,"This sample is not an instrument.");
  436.       goto ignore;
  437.       }
  438.    if ((i=code-80)>=samp.ctoctave[cur]) {
  439.       msg(Window,"Octave not defined.");
  440.       goto ignore;
  441.       }
  442.    k=(powr(2,i)-1)*(samp.oneshot[cur]+samp.repeat[cur]);
  443.    len=powr(2,i)*samp.oneshot[cur];
  444.    if (even(k)!=k) {
  445.       msg(Window,"Warning: Octave address not on a word boundry!");
  446.       k=even(k);
  447.       }
  448.    if (even(len)!=len) {
  449.       msg(Window,"Warning: oneshot length not even!");
  450.       len=even(len);
  451.       }
  452.    IOB.ioa_Request.io_Unit=1;
  453.    tochan (&IOB,samp.lmem[cur]+k,len,samp.rate[cur],1);
  454.    k=k+len;
  455.    j=samp.repeat[cur];
  456.    if (even(j)!=j) {
  457.       msg(Window,"Warning: repeat length not even!");
  458.       j=even(j);
  459.       }
  460.    if (j!=0)
  461.       tochan (&IOB, samp.lmem[cur]+k,powr(2,i)*j,samp.rate[cur],0);
  462.    while (class!=RAWKEY || code<127) {
  463.       if((message=(struct IntuiMessage *)GetMsg(Window->UserPort))==0)
  464.          Wait(1<<Window->UserPort->mp_SigBit);
  465.       else {
  466.          class=message->Class;
  467.          code=message->Code;
  468.          ReplyMsg(message);
  469.          }
  470.       }
  471.    IOB.ioa_Request.io_Unit=3;
  472.    IOB.ioa_Request.io_Command=CMD_RESET;
  473.    DoIO (&IOB);
  474.    goto ignore;
  475.    }
  476.  
  477. if (class==MENUPICK && code==MENUNULL) {
  478.     if (mousey<GPP-5) goto ignore;       /* play only if near gadget */
  479.     play(Window,&IOB,0,lastp,&samp,cur);
  480.     goto ignore;
  481.     }
  482.  
  483.  
  484. menunum=MENUNUM(code);
  485. itemnum=ITEMNUM(code);
  486. subnum=SUBNUM(code);
  487.  
  488. if (menunum==2 && itemnum==2) {            /* monitor the digitizer */
  489.    msg(Window,"Press the left mouse button to exit.");
  490.    switch (subnum) {
  491.  
  492.    case 0: listen(STEREO);
  493.            break;
  494.    case 1: listen(RIGHT);
  495.            break;
  496.    case 2: listen(LEFT);
  497.            }
  498.    msg(Window,"");
  499.    goto ignore;
  500.    }
  501.  
  502. if (menunum==2 && itemnum==3)  {  /* RECORD */
  503.    if ((i=getslot(Window,&samp))==-1) goto ignore;
  504.    p1=(char *)1;p2=(char *)1;
  505.    Forbid();
  506.    memory=frags();
  507.    if (memory<8000) {
  508.       Permit();
  509.       nomem(Window);
  510.       goto ignore;
  511.       }
  512.    if (subnum==0) {      /* stereo */
  513.       memory=memory/2;
  514.       p1=AllocMem(memory,0);
  515.       if (p1!=0) p2=AllocMem(memory,0);
  516.       if (p2==0) FreeMem(p1,memory);
  517.       }
  518.    else  
  519.       p1=AllocMem(memory,0);
  520.    Permit();
  521.    if (p1==0 || p2==0) {
  522.       nomem(Window);
  523.       goto ignore;
  524.       }
  525.    switch (subnum) {
  526.       case 0: k=STEREO;
  527.               samp.lmem[i]=p1;
  528.               samp.rmem[i]=p2;
  529.               break;
  530.       case 1: k=RIGHT;
  531.               samp.rmem[i]=p1;
  532.               samp.lmem[i]=p1; /* use only to find free sample elsewhere */
  533.               break;
  534.       case 2: k=LEFT;
  535.               samp.lmem[i]=p1;
  536.               samp.rmem[i]=p1;    /* only for compatibility with prev.*/
  537.               break;
  538.       default: msg(Window,"BUG... code 01");
  539.               goto ignore;
  540.       }
  541.    samp.type[i]=k;
  542.    msg(Window,"Monitoring... Press left mouse button to start recording.");
  543.    listen(k);   /* listen before we start recording */
  544.  
  545.    samplen=digitze (Window,p1,p2,record_delay,memory,k);
  546.    if (samplen==0) {
  547.       msg(Window,"BUG... code 02");
  548.       FreeMem(samp.lmem[i],memory);
  549.       if (k==STEREO) FreeMem(samp.rmem[i],memory);
  550.       samp.lmem[i]=0;
  551.       goto ignore;
  552.       }
  553.    if (samplen==memory)
  554.       msg(Window,"Memory filled.");
  555.    else {
  556.       FreeMem(rup(p1+samplen),rdn(memory-samplen));
  557.       sprintf(line,"%d bytes used in this recording.",samplen);
  558.       if (k==STEREO) {
  559.          FreeMem(rup(p2+samplen),rdn(memory-samplen));
  560.          sprintf(line,"%d bytes used in this recording.",samplen*2);
  561.          }
  562.       msg(Window,line);
  563.       }
  564.    samp.length[i]=samplen;
  565.    samp.rate[i]=127+45*record_delay;
  566.    if (k==STEREO) samp.rate[i]=samp.rate[i]*5/6;
  567.    line[0]=0;
  568.    getstr(Window,line,"Enter a label for this sample:",400);
  569.    if (line[0]==0) strcpy(line,"A Nameless Sound");
  570.    samp.name[i]=AllocMem(strlen(line)+1,0);
  571.    if (samp.name[i]==0) {
  572.       nomem(Window);
  573.       FreeMem(samp.lmem[i],samplen);
  574.       samp.lmem[i]=0;
  575.       if (k==STEREO) FreeMem(samp.rmem[i],samplen);
  576.       goto ignore;
  577.       }
  578.    strcpy(samp.name[i],line);    /* move filename to premenant place */
  579.    if (samp.lmem[cur]!=0)
  580.      PutName(Window,samp.name[cur],cur,REG_VID);
  581.    PutName(Window,samp.name[i],i,REV_VID);
  582.    cur=i;
  583.    msg(Window,"");     /* clear input line */
  584.    samp.sm[cur]=0;
  585.    samp.em[cur]=samp.length[cur];
  586.    position=0;
  587.    lastp=0;
  588.    prop_e->HorizPot=0xFFFF;
  589.    prop_p->HorizPot=0;
  590.    prop_s->HorizPot=0;
  591.    RefreshGadgets(gadget_s,Window,NULL);
  592.    }
  593.  
  594. if (menunum==2 && itemnum==0) {    /* change default recording speed */
  595.    i=getint(Window,127+45*record_delay,124,999,
  596.             "Enter a new recording period:",440);
  597.    record_delay=(i-127)/45;
  598.    sprintf(line,"%d is as close as I can get.",127+45*record_delay);
  599.    msg(Window,line);
  600.    }
  601.  
  602.   /* show numeric values of input */
  603. if (menunum==2 && itemnum==1) {
  604.    level(Window);
  605.    goto ignore;
  606.    }
  607.  
  608. if (menunum==3 && itemnum==0) {                   /* load a sample */
  609.    if (load_samp(Window,&cur,&samp,path)==-1)
  610.       goto ignore;
  611.    samp.sm[cur]=0;
  612.    samp.em[cur]=samp.length[cur];
  613.    position=0;
  614.    lastp=0;
  615.    prop_e->HorizPot=0xFFFF;ope=0xFFFF;
  616.    prop_p->HorizPot=0;opp=0;
  617.    prop_s->HorizPot=0;ops=0;
  618.    RefreshGadgets(gadget_s,Window,NULL);
  619.    }
  620.  
  621. if (menunum==3 && itemnum==1) {      /* save AS ... */
  622.    strcpy(line,samp.name[cur]);
  623.    if (getfile(Window,line,path,"SAVE","Save a Sample")==-1) goto ignore;
  624.    strcpy(buf,path);
  625.    add(buf,line);   /* appends a file or directory to a path */
  626.    switch (subnum) {
  627.    case 0: save_IFF(Window,cur,&samp,buf,FALSE);
  628.            break;
  629.    case 1: save_samp(Window,cur,&samp,buf);
  630.            break;
  631.    case 2: save_IFF(Window,cur,&samp,buf,TRUE);
  632.    }
  633.    diskchange=TRUE;
  634.    goto ignore;
  635.    }
  636.  
  637. if (menunum==3 && itemnum==2) {      /* save ... */
  638.    strcpy(buf,path);
  639.    add(buf,samp.name[cur]);
  640.    switch (subnum) {
  641.    case 0: save_IFF(Window,cur,&samp,buf,FALSE);
  642.            break;
  643.    case 1: save_samp(Window,cur,&samp,buf);
  644.            break;
  645.    case 2: save_IFF(Window,cur,&samp,buf,TRUE);
  646.    }
  647.    diskchange=TRUE;
  648.    goto ignore;
  649.    }
  650.  
  651.            /*play entire sample */
  652.  
  653. if (class==GADGETUP && gad->TopEdge==GPW) {
  654.    play(Window,&IOB,0,samp.length[cur],&samp,cur);
  655.    goto ignore;
  656.    }
  657.  
  658.             /* play range  */
  659.  
  660. if (class==GADGETUP && gad->TopEdge==GPR) {
  661.    play(Window,&IOB,samp.sm[cur],samp.em[cur]-samp.sm[cur],&samp,cur);
  662.    goto ignore;
  663.    } 
  664.  
  665.  
  666. if (menunum==0 && itemnum==0) {     /* delete a range */
  667.    if (samp.em[cur]<=samp.sm[cur]) {
  668.       msg(Window,"Markers not set.");
  669.       goto ignore;
  670.       }
  671.    if (samp.em[cur]>=samp.length[cur] && samp.sm[cur]==0) goto whole;
  672.    msg(Window,"Working...");
  673.  
  674.    i=samp.sm[cur];  /* start deleting including this byte */
  675.    j=samp.em[cur];
  676.  
  677.    k=rup(samp.length[cur]-(j-i));
  678.  
  679.    if (j<samp.length[cur])
  680.       movmem(samp.lmem[cur]+j,samp.lmem[cur]+i,samp.length[cur]-j);
  681.  
  682.     if (k<rup(samp.length[cur]))
  683.        FreeMem(samp.lmem[cur]+k,rup(j-i));
  684.  
  685.    if (samp.type[cur]==STEREO) {
  686.       if (j<samp.length[cur]) 
  687.          movmem(samp.rmem[cur]+j,samp.rmem[cur]+i,samp.length[cur]-j);
  688.       if (k<rup(samp.length[cur]))
  689.          FreeMem(samp.rmem[cur]+k,rup(j-i));
  690.       }
  691.  
  692.  
  693.   samp.length[cur]=samp.length[cur]-(j-i);
  694.   msg(Window,"");
  695.   samp.sm[cur]=0;
  696.   samp.em[cur]=samp.length[cur];
  697.   prop_s->HorizPot=0;
  698.   prop_e->HorizPot=0xFFFF;
  699.   prop_p->HorizPot=0;
  700.   lastp=0;
  701.   position=0;
  702.   RefreshGadgets(gadget_s,Window,NULL);
  703.   }
  704.  
  705. if (menunum==0 && itemnum==1) {    /* delete entire sample */
  706.  
  707. whole:         /* jump here from delete range if entire sample */
  708.    if (samp.lmem[cur]==0) goto ignore;
  709.    FreeMem(samp.lmem[cur],samp.length[cur]);
  710.    if (samp.type[cur]==STEREO)
  711.       FreeMem(samp.rmem[cur],samp.length[cur]);
  712.    FreeMem(samp.name[cur],strlen(samp.name[cur])+1);
  713.    samp.lmem[cur]=0;
  714.    samp.rmem[cur]=0;
  715.    samp.length[cur]=0;
  716.    samp.name[cur]=0;
  717.    samp.repeat[cur]=0;
  718.    samp.oneshot[cur]=0;
  719.    samp.cycles[cur]=0;
  720.    samp.ctoctave[cur]=0;
  721.    samp.sm[cur]=0;
  722.    samp.em[cur]=0;
  723.    i=0;
  724.    while(samp.lmem[i]==0 && i<MAX_SAMPLES) i++;
  725.    PutName(Window,"",cur,REG_VID);
  726.    if (i!=MAX_SAMPLES) {
  727.       cur=i;
  728.       PutName(Window,samp.name[cur],cur,REV_VID);
  729.       prop_s->HorizPot=samp.sm[cur]*(0xFFFF/samp.length[cur]);
  730.       prop_e->HorizPot=samp.em[cur]*(0xFFFF/samp.length[cur]);
  731.       prop_p->HorizPot=0;
  732.       RefreshGadgets(gadget_s,Window,NULL);
  733.       lastp=0;
  734.       position=0;
  735.       }
  736.    else
  737.       cur=0;
  738.    }
  739.  
  740. if (menunum==0 && itemnum==2) {      /* insert here */
  741.    msg(Window,"Please click Slot that contains the marked range.");
  742.    i=pickslot(Window,&samp);
  743.    move(Window,&samp,samp.sm[i],samp.em[i],position,i,cur);
  744.    msg(Window,"Range inserted.");
  745.    }
  746.  
  747. if (menunum==1 && itemnum==0) {        /* flip cur sample */
  748.    if (samp.lmem[cur]==0) goto ignore;
  749.    msg(Window,"Flipping...");
  750.  
  751.    flip(samp.lmem[cur],samp.length[cur]);
  752.    if (samp.type[cur]==STEREO) {
  753.       flip(samp.rmem[cur],samp.length[cur]);
  754.    }
  755.    msg(Window,"");
  756.    if (autograph==TRUE) goto graphit;
  757.    goto ignore;
  758.    }
  759.  
  760. if (menunum==1 && itemnum==1) {  /* graph sample */
  761.    graphit:
  762.    graph(Window,&samp,cur);
  763.    sprintf(line,"First sample graphed: %d  Last sample graphed: %d",
  764.            *(samp.lmem[cur]+samp.sm[cur]),*(samp.lmem[cur]+samp.em[cur]-1));
  765.    msg(Window,line);
  766.    goto update;
  767.    }
  768.  
  769. if (menunum==1 && itemnum==2) {   /* create a new instrument */
  770.    if (samp.lmem[cur]==0) goto ignore;
  771.  
  772. /* create list of octaves in assending order */
  773.    k=0;
  774.    for (i=0;i<MAX_SAMPLES;i++)
  775.       if (samp.lmem[i]!=0)
  776.          oct[k++]=i;
  777.  
  778. /* sort */
  779.  
  780.    for (i=0;i<k-1;i++)
  781.       for (j=i+1;j<k;j++)
  782.          if (samp.length[oct[i]]>samp.length[oct[j]]) {
  783.             temp=oct[i];
  784.             oct[i]=oct[j];
  785.             oct[j]=temp;
  786.             }
  787.  
  788.    if ((i=getslot(Window,&samp))==-1) goto ignore;
  789.    len=(powr(2,k)-1)*samp.length[oct[0]];
  790.    p1=AllocMem(len,MEMF_CHIP);
  791.    if (p1==0) {
  792.       msg(Window,"Not Enough Chip Memory.");
  793.       goto ignore;
  794.       }
  795.    samp.length[i]=len;
  796.    samp.type[i]=RIGHT;
  797.    samp.rate[i]=samp.rate[oct[0]];
  798.    samp.lmem[i]=p1;
  799.    samp.rmem[i]=p1;
  800.    samp.ctoctave[i]=k;
  801.    samp.em[i]=samp.length[i];
  802.    samp.oneshot[i]=samp.sm[oct[0]];
  803.    samp.repeat[i]=samp.length[oct[0]]-samp.sm[oct[0]];
  804.  
  805.    /* move all octaves into new instrument */
  806.  
  807.    len=samp.length[oct[0]];
  808.    temp=0;
  809.    for (j=0;j<k;j++) {
  810.       if (samp.length[oct[j]]!=len)
  811.          msg(Window,"Warning, an octave length is not the correct size.");
  812.       movmem(samp.lmem[oct[j]],samp.lmem[i]+temp,len);
  813.       temp=temp+len;
  814.       len=len*2;
  815.       }
  816.  
  817.  
  818.    /* get a name for this sample */
  819.  
  820.    line[0]=0;
  821.    getstr(Window,line,"Enter a name for this instrument:",400);
  822.    if (line[0]==0) strcpy(line,"Lazy typer");
  823.    samp.name[i]=AllocMem(strlen(line)+1,0);
  824.    if (samp.name[i]==0) {
  825.       nomem(Window);
  826.       FreeMem(samp.lmem[i],samp.length[i]);
  827.       samp.lmem[i]=0;
  828.       samp.ctoctave[i]=0;
  829.       samp.oneshot[i]=0;
  830.       goto ignore;
  831.       }
  832.    strcpy(samp.name[i],line);
  833.  
  834.   samp.cycles[i]=getint(Window,8,0,256,"Enter SamplesPerHiCycle",256);
  835.  
  836.  /* sampperhicycle should be power of 2 for most programs */
  837.    j=FALSE;
  838.    for (k=0;k<16;k++)
  839.       if (powr(2,k)==samp.cycles[i]) j=TRUE;
  840.    if (j==FALSE)
  841.        msg(Window,"Warning: SamplesPerHiCycle may need to be a power of 2.");
  842.    else
  843.       msg(Window,"Instrument created.");
  844.   /* highlight new instrument */
  845.  
  846.    PutName(Window,samp.name[cur],cur,REG_VID);
  847.    PutName(Window,samp.name[i],i,REV_VID);
  848.    cur=i;
  849.    }
  850.  
  851. /* cut period in half by eliminating samples */
  852.  
  853. if (menunum==1 && itemnum==3) {
  854.    if (samp.lmem[cur]==0) goto ignore;
  855.    if (samp.type[cur]==STEREO) {
  856.       msg(Window,"Sorry, this command does not work with stereo.");
  857.       goto ignore;
  858.       }
  859.    if ((i=getslot(Window,&samp))==-1) goto ignore;
  860.    line[0]=0;
  861.    getstr(Window,line,"Enter a name for the new sample:",400);
  862.    if (line[0]==0) strcpy(line,"*2");
  863.    samp.name[i]=AllocMem(strlen(line)+1,0);
  864.    if (samp.name[i]==0) {
  865.       nomem(Window);
  866.       goto ignore;
  867.       }
  868.    msg(Window,"Working...");
  869.    strcpy(samp.name[i],line);    /* move filename to permenant place */
  870.    samp.length[i]=samp.length[cur]/2;
  871.    samp.lmem[i]=AllocMem(samp.length[i],0);
  872.    if (samp.lmem[i]==0) {
  873.       nomem(Window);
  874.       samp.name[i]=0;
  875.       samp.length[i]=0;
  876.       goto ignore;
  877.       }
  878.    samp.type[i]=samp.type[cur];
  879.    samp.rate[i]=samp.rate[cur];
  880.    samp.em[i]=samp.length[i];
  881.    samp.rmem[i]=samp.lmem[i];
  882.    j=0;
  883.    for (k=0;k<samp.length[cur];k=k+2)
  884.       *(samp.lmem[i]+j++)=*(samp.lmem[cur]+k);
  885.  
  886.    PutName(Window,samp.name[cur],cur,REG_VID);
  887.    PutName(Window,samp.name[i],i,REV_VID);
  888.    cur=i;
  889.    msg(Window,"");
  890.    }
  891.    
  892.  
  893. /* double period by interpolating */
  894.  
  895. if (menunum==1 && itemnum==4) {
  896.    if (samp.lmem[cur]==0) goto ignore;
  897.    if (samp.type[cur]==STEREO) {
  898.       msg(Window,"Sorry, this command does not work with stereo.");
  899.       goto ignore;
  900.       }
  901.    if ((i=getslot(Window,&samp))==-1) goto ignore;
  902.    line[0]=0;
  903.    getstr(Window,line,"Enter a name for the new sample:",400);
  904.    if (line[0]==0) strcpy(line,"/2");
  905.    samp.name[i]=AllocMem(strlen(line)+1,0);
  906.    if (samp.name[i]==0) {
  907.       nomem(Window);
  908.       goto ignore;
  909.       }
  910.    msg(Window,"Working...");
  911.    strcpy(samp.name[i],line);    /* move filename to permenant place */
  912.    samp.length[i]=samp.length[cur]*2;
  913.    samp.lmem[i]=AllocMem(samp.length[i],0);
  914.    if (samp.lmem[i]==0) {
  915.       nomem(Window);
  916.       samp.name[i]=0;
  917.       samp.length[i]=0;
  918.       goto ignore;
  919.       }
  920.    samp.type[i]=samp.type[cur];
  921.    samp.rate[i]=samp.rate[cur];
  922.    samp.em[i]=samp.length[i];
  923.    samp.rmem[i]=samp.lmem[i];
  924.    j=0;
  925.    for (k=0;k<samp.length[cur];k++) {
  926.       *(samp.lmem[i]+j++)=*(samp.lmem[cur]+k);
  927.       *(samp.lmem[i]+j++)=(*(samp.lmem[cur]+k)+*(samp.lmem[cur]+k+1))/2;
  928.       }
  929.    *(samp.lmem[i]+j-1)=*(samp.lmem[cur]+k-1);    /* last interp. is wrong */
  930.  
  931.    PutName(Window,samp.name[cur],cur,REG_VID);
  932.    PutName(Window,samp.name[i],i,REV_VID);
  933.    cur=i;
  934.    msg(Window,"");
  935.    }
  936.  
  937. if (menunum==1 && itemnum==5) {
  938.    if (subnum==0) {
  939.       autograph=TRUE;
  940.       goto graphit;
  941.       }
  942.    if (subnum==1) autograph=FALSE;
  943.    }
  944.  
  945. if (menunum==0 && itemnum==3) {      /* enter new playback rate */
  946.    if (samp.lmem[cur]==0) goto ignore;
  947.    samp.rate[cur]=getint(Window,samp.rate[cur],124,700,
  948.                   "Enter a new playback period:",440);
  949.    }
  950.  
  951. /* copy range to a new slot */
  952.  
  953. if (menunum==0 && itemnum==4) {
  954.    if (samp.lmem[cur]==0) goto ignore;
  955.    len=samp.em[cur]-samp.sm[cur];
  956.    if (len<=1 || len>8000000) {
  957.       msg(Window,"Markers Not Set");
  958.       goto ignore;
  959.       }
  960.    if ((i=getslot(Window,&samp))==-1) goto ignore;
  961.    line[0]=0;
  962.    getstr(Window,line,"Enter a label for the new sample",400);
  963.    if (line[0]==0) strcpy(line,"A Nameless Sound");
  964.    samp.name[i]=AllocMem(strlen(line)+1,0);
  965.    if (samp.name[i]==0) {
  966.       nomem(Window);
  967.       goto ignore;
  968.       }
  969.    strcpy(samp.name[i],line);
  970.    if ((samp.lmem[i]=AllocMem(len,0))==0) {
  971.       nomem(Window);
  972.       FreeMem(samp.name[i],strlen(samp.name[i])+1);
  973.       goto ignore;
  974.       }
  975.  
  976.    samp.rmem[i]=samp.lmem[i];
  977.  
  978.    if (samp.type[cur]==STEREO)
  979.       if ((samp.rmem[i]=AllocMem(len,0))==0) {
  980.          FreeMem(samp.lmem[i],len);
  981.          FreeMem(samp.name[i],strlen(samp.name[i])+1);
  982.          nomem(Window);
  983.          samp.lmem[i]=0;
  984.          samp.name[i]=0;
  985.          goto ignore;
  986.          }
  987.  
  988.    msg(Window,"Working...");
  989.  
  990.    movmem(samp.lmem[cur]+samp.sm[cur],samp.lmem[i],len);
  991.    if (samp.type[cur]==STEREO)
  992.       movmem(samp.rmem[cur]+samp.sm[cur],samp.rmem[i],len);
  993.    msg(Window,"");
  994.    samp.length[i]=len;
  995.    samp.rate[i]=samp.rate[cur];
  996.    samp.type[i]=samp.type[cur];
  997.    PutName(Window,samp.name[cur],cur,REG_VID);
  998.    cur=i;
  999.    PutName(Window,samp.name[cur],cur,REV_VID);
  1000.    samp.em[cur]=samp.length[cur];
  1001.    samp.sm[cur]=0;
  1002.    prop_e->HorizPot=0xFFFF;ope=0xFFFF;
  1003.    prop_p->HorizPot=0;opp=0;
  1004.    prop_s->HorizPot=0;ops=0;
  1005.    RefreshGadgets(gadget_s,Window,NULL);
  1006.    }
  1007.  
  1008. /* append a slot to another slot */
  1009.  
  1010. if (menunum==0 && itemnum==5) {
  1011.    if (samp.lmem[cur]==0) goto ignore;
  1012.    msg(Window,"Click slot to append");
  1013.    i=pickslot(Window,&samp);
  1014.    msg(Window,"Click slot to append this to...");
  1015.    k=pickslot(Window,&samp);
  1016.    len=samp.length[i]+samp.length[k];
  1017.    move(Window,&samp,0,samp.length[i],samp.length[k],i,k);
  1018.    }
  1019.    
  1020. if (menunum==4 && itemnum==0) {    /* about */
  1021.    aboutps(Window);
  1022.    goto ignore;
  1023.    }
  1024.  
  1025. /* Break up a stereo into two new slots */
  1026.  
  1027. if (menunum==0 && itemnum==7) {
  1028.    if (samp.lmem[cur]==0) goto ignore;
  1029.    if (samp.type[cur]!=STEREO) {
  1030.       msg(Window,"Sample must be stereo.");
  1031.       goto ignore;
  1032.       }
  1033.    if ((i=getslot(Window,&samp))==-1) goto ignore;
  1034.    samp.name[i]=AllocMem(strlen(samp.name[cur])+2,0);
  1035.    if (samp.name[i]==0) {
  1036.       nomem(Window);
  1037.       goto ignore;
  1038.       }
  1039.    *samp.name[i]='L';
  1040.    strcpy(samp.name[i]+1,samp.name[cur]);
  1041.    samp.lmem[i]=samp.lmem[cur];
  1042.    samp.rmem[i]=samp.lmem[cur];
  1043.    samp.type[i]=LEFT;
  1044.    samp.length[i]=samp.length[cur];
  1045.    samp.rate[i]=samp.rate[cur];
  1046.    samp.sm[i]=0;
  1047.    samp.em[i]=samp.length[i];
  1048.    x=AllocMem(strlen(samp.name[cur])+2,0);
  1049.    if (x==0) {
  1050.       nomem(Window);
  1051.       FreeMem(samp.name[i],strlen(samp.name[i]+1));
  1052.       samp.lmem[i]=0;
  1053.       samp.rmem[i]=0;
  1054.       samp.length[i]=0;
  1055.       goto ignore;
  1056.       }
  1057.    *x='R';
  1058.    strcpy(x+1,samp.name[cur]);
  1059.    FreeMem(samp.name[cur],strlen(samp.name[cur])+1);
  1060.    samp.name[cur]=x;
  1061.    samp.lmem[cur]=samp.rmem[cur];
  1062.    samp.type[cur]=RIGHT;
  1063.    PutName(Window,samp.name[cur],cur,REV_VID);
  1064.    PutName(Window,samp.name[i],i,REG_VID);
  1065.    msg(Window,"Created seperate left and right channels.");
  1066.    }
  1067.    
  1068. /* create stereo from two mono samples */
  1069.  
  1070. if (menunum==0 && itemnum==6) {
  1071.    if (samp.lmem[cur]==0) goto ignore;
  1072.    msg(Window,"Click slot for left channel.");
  1073.    i=pickslot(Window,&samp);
  1074.    if (samp.type[i]==STEREO) {
  1075.       msg(Window,"Sample must be mono.");
  1076.       goto ignore;
  1077.       }
  1078.    msg(Window,"Click slot for right channel.");
  1079.    k=pickslot(Window,&samp);
  1080.    if (samp.type[k]==STEREO) {
  1081.       msg(Window,"Sample must be mono.");
  1082.       goto ignore;
  1083.       }
  1084.    if (k==i) {
  1085.       msg(Window,"Samples must be in different slots.");
  1086.       goto ignore;
  1087.       }
  1088.    if (samp.length[i]<samp.length[k]) {ss=i;sl=k;}
  1089.    else {ss=k;sl=i;}
  1090.    if (samp.length[i]!=samp.length[k])
  1091.    FreeMem(samp.lmem[sl]+samp.length[ss],samp.length[sl]-samp.length[ss]);
  1092.    FreeMem(samp.name[sl],strlen(samp.name[sl])+1);
  1093.    samp.lmem[ss]=samp.lmem[i];
  1094.    samp.rmem[ss]=samp.rmem[k];
  1095.    samp.type[ss]=STEREO;
  1096.    PutName(Window,"",sl,REG_VID);
  1097.    cur=ss;
  1098.    samp.lmem[sl]=0;
  1099.    samp.rmem[sl]=0;
  1100.    samp.length[sl]=0;
  1101.    samp.name[sl]=0;
  1102.    PutName(Window,samp.name[cur],cur,REV_VID);
  1103.    msg(Window,"Current sample is now stereo.");
  1104.    }
  1105.  
  1106.  
  1107. /** print Status information at the bottom of the screen **/
  1108.  
  1109. update:
  1110. if (samp.lmem[cur]!=0 && samp.em[cur]>samp.length[cur])
  1111.      samp.em[cur]=samp.length[cur];
  1112.  
  1113.  
  1114. memory=frags();
  1115. sprintf(line,"Sample length: %7.7d  playback rate: %4.4d",
  1116.         samp.length[cur],samp.rate[cur]);
  1117. putxy(Window,23,164,line,WHITE,BLACK);
  1118.  
  1119. sprintf(line,"Current position: %7.7d Start/End mark: %7.7d %7.7d",
  1120.         position,samp.sm[cur],samp.em[cur]);
  1121. putxy(Window,23,172,line,WHITE,BLACK);
  1122.  
  1123. sprintf(line,"Memory for recording: %7.7d record rate: %4.4d",
  1124.         memory,127+record_delay*45);
  1125. putxy(Window,23,180,line,WHITE,BLACK);
  1126. goto ignore;
  1127. }
  1128.  
  1129.  
  1130. /***********************************/
  1131. /* Play a digitized sample         */
  1132. /***********************************/
  1133.  
  1134. play(Window,IOB,start,len,samp,it)
  1135. struct Samp *samp;
  1136. struct IOAudio *IOB;
  1137. struct Window *Window;
  1138. int len,start,it;
  1139.  
  1140. {
  1141. struct IOAudio *IOBlks[4];
  1142. struct MsgPort *port;
  1143. int k,i,firstloop;
  1144. int unit_num=0;
  1145. int off,thislen;
  1146. if (len==0) return(0);
  1147. if (len<0) {
  1148.    msg(Window,"Invalid Range... Check Your Markers.");
  1149.    return(0);
  1150.    }
  1151.  
  1152. if (samp->type[it]==LEFT || samp->type[it]==STEREO) unit_num|=1;
  1153. if (samp->type[it]==RIGHT || samp->type[it]==STEREO) unit_num|=2;
  1154.  
  1155. /** allocate memory for Audio IOB's **/
  1156.  
  1157. for (k=0;k<4;k++) {
  1158.    if ((IOBlks[k]=AllocMem(sizeof(struct IOAudio),0))==0) {
  1159.       nomem(Window);
  1160.       while(k-->0)
  1161.          FreeMem(IOBlks[k],sizeof(struct IOAudio));
  1162.       return(0);
  1163.       }
  1164.    if ((port=(struct MsgPort *)CreatePort("Rize-samps", 0)) == 0) {
  1165.       msg (Window,"can't open port");
  1166.       return(0);
  1167.       }
  1168.    movmem(IOB,IOBlks[k],sizeof(struct IOAudio));
  1169.    IOBlks[k]->ioa_Request.io_Message.mn_ReplyPort = port;
  1170.    }
  1171.  
  1172. IOB->ioa_Request.io_Unit=3;
  1173. IOB->ioa_Request.io_Command=CMD_RESET;
  1174. DoIO (IOB);
  1175.  
  1176.  
  1177. k=0;      /* indicates which of the two buffers to use */
  1178. off=0;    /* our position in the sample relative to start */
  1179. thislen=BUFSIZE;   /* length of current chuck of sample we are playing */
  1180.  
  1181.  
  1182. IOB->ioa_Request.io_Command=CMD_STOP;
  1183. DoIO(IOB);
  1184.  
  1185. firstloop=TRUE;
  1186.  
  1187.  
  1188. do {
  1189.  
  1190. if (off+BUFSIZE>len) thislen=len-off;
  1191. if (thislen==0) thislen=2;
  1192.  
  1193. if ((unit_num&2)==2) {
  1194.    movmem(samp->rmem[it]+off+start,bufR[k],BUFSIZE);
  1195.    IOBlks[2+k]->ioa_Request.io_Unit=2;
  1196.    tochan (IOBlks[2+k],bufR[k],thislen,samp->rate[it],1);
  1197.    }
  1198.  
  1199. if ((unit_num&1)==1) {
  1200.    movmem(samp->lmem[it]+off+start,bufL[k],BUFSIZE); /* set 1st buffer up */
  1201.    IOBlks[k]->ioa_Request.io_Unit=1;
  1202.    tochan (IOBlks[k],bufL[k],thislen,samp->rate[it],1);
  1203.    }
  1204.  
  1205. if (k==0) k=1; else k=0;
  1206.  
  1207. off=off+BUFSIZE;
  1208.  
  1209. if (firstloop==TRUE) {
  1210.    IOB->ioa_Request.io_Unit=unit_num;
  1211.    IOB->ioa_Request.io_Command=CMD_START;
  1212.    DoIO(IOB);
  1213.    firstloop=FALSE;
  1214.    }
  1215.  
  1216. else {
  1217.    if ((unit_num&1)==1) WaitIO (IOBlks[k]);
  1218.    if ((unit_num&2)==2) WaitIO (IOBlks[2+k]);
  1219.    }
  1220.  
  1221. } while (thislen==BUFSIZE);
  1222.  
  1223. if (k==0) k=1;    /* wait for last request to finish */
  1224. else k=0;
  1225. if ((unit_num&1)==1) WaitIO (IOBlks[k]);
  1226. if ((unit_num&2)==2) WaitIO (IOBlks[2+k]);
  1227.  
  1228. IOB->ioa_Request.io_Unit=3;
  1229. IOB->ioa_Request.io_Command=CMD_RESET;
  1230. DoIO (IOB);
  1231.  
  1232. /* free iob's memory */
  1233.  
  1234.    for (i=0;i<4;i++) {
  1235.       port = IOBlks[i]->ioa_Request.io_Message.mn_ReplyPort;
  1236.       if (port != 0)
  1237.          DeletePort (port);
  1238.       FreeMem(IOBlks[i],sizeof(struct IOAudio));   /* finished with this IOB */
  1239.       }
  1240. }
  1241.